//! 核心解析器实现
//! 
//! 提供 Parser 结构体和基础 Token 操作方法

use crate::ast::*;
use crate::error::{AssemblerError, Result};
use crate::lexer::{Lexer, Token};

/// 语法分析器
pub struct Parser {
    pub(super) lexer: Lexer,
    pub(super) current_token: Token,
    pub(super) peek_token: Option<Token>,
}

impl Parser {
    /// 创建新的语法分析器
    pub fn new(mut lexer: Lexer) -> Result<Self> {
        let current_token = lexer.next_token()?;
        let peek_token = Some(lexer.next_token()?);
        Ok(Self {
            lexer,
            current_token,
            peek_token,
        })
    }

    /// 从源代码字符串创建解析器
    pub fn from_source(source: &str) -> Result<Self> {
        let lexer = Lexer::new(source);
        Self::new(lexer)
    }

    /// 前进到下一个 Token
    pub(super) fn advance(&mut self) -> Result<()> {
        self.current_token = self.peek_token.take().unwrap_or(Token::Eof);
        if self.current_token != Token::Eof {
            self.peek_token = Some(self.lexer.next_token()?);
        }
        Ok(())
    }

    /// 检查当前 Token 是否匹配
    pub(super) fn check_token(&self, token: &Token) -> bool {
        std::mem::discriminant(&self.current_token) == std::mem::discriminant(token)
    }

    /// 期望当前 Token 是特定类型
    pub(super) fn expect_token(&mut self, expected: &Token) -> Result<()> {
        if !self.check_token(expected) {
            let (line, column) = self.lexer.position();
            return Err(AssemblerError::ParseError {
                message: format!("期望 {:?}, 但得到 {:?}", expected, self.current_token),
                line,
                column,
            });
        }
        self.advance()?;
        Ok(())
    }

    /// 解析程序
    pub fn parse_program(&mut self) -> Result<Program> {
        use super::instruction::InstructionParser;
        
        let mut statements = Vec::new();

        while !self.check_token(&Token::Eof) {
            // 跳过空行
            if self.check_token(&Token::Newline) {
                self.advance()?;
                continue;
            }

            // 检查是否是标签
            if let Some((label, line)) = self.try_parse_label()? {
                statements.push(Statement::Label(label, line));
                continue;
            }

            // 检查是否是数据定义（新增）
            if let Some(data_def) = self.try_parse_data_definition()? {
                statements.push(Statement::DataDefinition(data_def));
                continue;
            }

            // 解析指令
            let instruction = self.parse_instruction()?;
            statements.push(Statement::Instruction(instruction));

            // 跳过换行符
            if self.check_token(&Token::Newline) {
                self.advance()?;
            }
        }

        Ok(Program { statements })
    }

    /// 尝试解析标签
    fn try_parse_label(&mut self) -> Result<Option<(String, usize)>> {
        if let Token::Identifier(name) = &self.current_token {
            if let Some(Token::Colon) = self.peek_token.as_ref() {
                let label_name = name.clone();
                let (line, _) = self.lexer.position();
                self.advance()?; // 消费标识符
                self.advance()?; // 消费冒号
                return Ok(Some((label_name, line)));
            }
        }
        Ok(None)
    }

    /// 尝试解析数据定义（新增）
    fn try_parse_data_definition(&mut self) -> Result<Option<DataDefinition>> {
        let (line, _) = self.lexer.position();
        
        // 检查是否是数据定义指令
        // 支持两种格式：
        // 1. "定义字节 值1, 值2, ..." - 无标签
        // 2. "标签 定义字节 值1, 值2, ..." - 标签和数据定义在同一行
        let (label, data_type) = match &self.current_token {
            Token::Identifier(name) => {
                match name.as_str() {
                    "定义字节" => (None, Some(DataType::Byte)),
                    "定义字" => (None, Some(DataType::Word)),
                    _ => {
                        // 可能是标签，检查下一个token是否是数据定义指令
                        if let Some(Token::Identifier(next_name)) = self.peek_token.as_ref() {
                            match next_name.as_str() {
                                "定义字节" => {
                                    let label_name = name.clone();
                                    (Some(label_name), Some(DataType::Byte))
                                }
                                "定义字" => {
                                    let label_name = name.clone();
                                    (Some(label_name), Some(DataType::Word))
                                }
                                _ => (None, None),
                            }
                        } else {
                            (None, None)
                        }
                    }
                }
            }
            _ => (None, None),
        };
        
        if let Some(dt) = data_type {
            // 如果有标签，先消费标签
            if label.is_some() {
                self.advance()?; // 消费标签
            }
            
            // 消费数据定义指令
            self.advance()?; // 消费 "定义字节" 或 "定义字"
            
            // 解析数据值列表
            let mut values = Vec::new();
            
            while !self.check_token(&Token::Newline) && !self.check_token(&Token::Eof) {
                // 跳过逗号
                if self.check_token(&Token::Comma) {
                    self.advance()?;
                    // 检查是否是尾随逗号（逗号后是换行或文件结束）
                    if self.check_token(&Token::Newline) || self.check_token(&Token::Eof) {
                        // 尾随逗号，允许但忽略
                        break;
                    }
                }
                
                // 解析数据值
                let value = match &self.current_token {
                    Token::StringLiteral(s) => {
                        let str_val = s.clone();
                        self.advance()?;
                        DataValue::String(str_val)
                    }
                    Token::Number(n) => {
                        let num = *n;
                        self.advance()?;
                        DataValue::Immediate(num)
                    }
                    Token::Minus => {
                        // 处理负数：-数字
                        self.advance()?; // 消费减号
                        match &self.current_token {
                            Token::Number(n) => {
                                let num = -*n; // 取负值
                                self.advance()?;
                                DataValue::Immediate(num)
                            }
                            _ => {
                                let (line, column) = self.lexer.position();
                                return Err(AssemblerError::ParseError {
                                    message: "减号后期望数字".to_string(),
                                    line,
                                    column,
                                });
                            }
                        }
                    }
                    Token::Comma => {
                        // 连续的逗号（如 "10,,20"），这是错误
                        let (line, column) = self.lexer.position();
                        return Err(AssemblerError::ParseError {
                            message: "数据定义中不允许连续的逗号".to_string(),
                            line,
                            column,
                        });
                    }
                    _ => {
                        let (line, column) = self.lexer.position();
                        return Err(AssemblerError::ParseError {
                            message: "数据定义期望数字或字符串".to_string(),
                            line,
                            column,
                        });
                    }
                };
                
                values.push(value);
                
                // 如果下一个是换行或文件结束，停止
                if self.check_token(&Token::Newline) || self.check_token(&Token::Eof) {
                    break;
                }
            }
            
            if values.is_empty() {
                let (line, column) = self.lexer.position();
                return Err(AssemblerError::ParseError {
                    message: "数据定义至少需要一个值".to_string(),
                    line,
                    column,
                });
            }
            
            return Ok(Some(DataDefinition {
                label,
                data_type: dt,
                values,
                line,
            }));
        }
        
        Ok(None)
    }
}

